﻿/*======================================================================
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
========================================================================*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.Threading;
using BlueCurve.Common.Application;
using CrawlingApplication.Db;
using CrawlingApplication.Remoting;

namespace CrawlingApplication
{
    class Program : BlueCurve.Common.InteractiveConsole.BaseConsole
    {
        #region 'Configuration'

        /// <summary>
        /// Instance de la class de traitement
        /// </summary>
        private static Treatment s_treatment = new Treatment();
        /// <summary>
        /// Thread de la console interactive
        /// </summary>
        private static Thread s_console { get; set; }
        /// <summary>
        /// Thread du traitement
        /// </summary>
        private static Thread s_schedule { get; set; }
        
        #endregion



        #region 'Functions'

        static void Main(string[] args)
        {
            EndDeleteFile();
            s_console = new Thread(new ThreadStart(new Program().Run));
            s_schedule = new Thread(new ThreadStart(TreatmentSchedule.GetInstance.RunTreament));
            s_console.Start();
            s_schedule.Start();

            s_treatment.GetFilesToParse += new EventHandler(s_treatment_GetFilesToParse);
            s_treatment.Delefile += new Treatment.EventRaiseDelefile(s_treatment_Delefile);

            s_treatment.RunTreatment();
        }

        /// <summary>
        /// Supprimer un fichier de la base de données et du repository
        /// </summary>
        static void s_treatment_Delefile(object sender, Treatment.EventData e)
        {
            try
            {
                using (CrawlingApplicationdbDataContext db = new CrawlingApplicationdbDataContext())
                {
                    db.DeleteFile(e.path);
                }

                Tcpclient client = new Tcpclient();
                client.DeleteFile(e.path);
            }
            catch
            {
                using (StreamWriter writer = new StreamWriter("Todelete.txt", true, System.Text.Encoding.UTF8))
                {
                    writer.WriteLine(e.path);
                    writer.Close();
                }
            }
        }


        /// <summary>
        /// Fonction attaché a l'evenement arret de l'application
        /// </summary>
        private void StopApplication()
        {
            TreatmentSchedule.GetInstance.IsStop = false;
            while (TreatmentSchedule.GetInstance.AliveThreads > 0) { Thread.Sleep(150); }
            s_treatment.StopRun = false;
            while (s_treatment.AliveThreads > 0) { Thread.Sleep(150); }

            // Suicide de l'application
            Process.GetCurrentProcess().Kill();
        }


        /// <summary>
        /// Fonction attaché a l'evenement redemarrage de l'application
        /// </summary>
        private void RestartApplication()
        {
            TreatmentSchedule.GetInstance.IsStop = false;
            while (TreatmentSchedule.GetInstance.AliveThreads > 0) { Thread.Sleep(150); }
            s_treatment.StopRun = false;
            while (s_treatment.AliveThreads > 0) { Thread.Sleep(150); }

            // Enregistre l'application pour le redemarrage
            Restart.RestartApplication(string.Concat(System.Diagnostics.Process.GetCurrentProcess().ProcessName, ".exe"));
            // Suicide de l'application
            Process.GetCurrentProcess().Kill();
        }


        /// <summary>
        /// Termine la suppression des fichiers
        /// </summary>
        private static void EndDeleteFile()
        {
            if (File.Exists("Todelete.txt"))
            {
                string line;
                using (StreamReader reader = new StreamReader(File.Open("Todelete.txt", FileMode.Open, FileAccess.Read, FileShare.None)))
                {
                    while ((line = reader.ReadLine()) != null)
                    {
                        using (CrawlingApplicationdbDataContext db = new CrawlingApplicationdbDataContext())
                        {
                            db.DeleteFile(line);
                        }
                        try
                        {
                            Tcpclient client = new Tcpclient();
                            client.DeleteFile(line);
                        } catch {
                        }
                    }
                    reader.Close();
                }
                File.Delete("Todelete.txt");
            }
        }


        /// <summary>
        /// Demande de nouveaux fichiers à indexer au repository
        /// </summary>
        private static void s_treatment_GetFilesToParse(object sender, EventArgs e)
        {
            try
            {
                Tcpclient client = new Tcpclient();
                List<string> datas = client.GetListFilesToParse(200);
                if (datas != null)
                {
                    using (CrawlingApplicationdbDataContext db = new CrawlingApplicationdbDataContext())
                    {
                        datas.ForEach(
                            delegate(string path)
                            {
                                db.AddFile(path);
                            });
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
                
        #endregion
        
        /// <summary>
        /// Charge les commandes de la console
        /// </summary>
        protected override void LoadCommands()
        {
            this.Commands.Add("-stop",
                new Dictionary<Action, string>()
                {
                    { () => StopApplication(), "Arrete l'application" }
                });
           this.Commands.Add("-restart",
                new Dictionary<Action, string>()
                {
                    { () => RestartApplication(), "Redémarre l'application" }
                });
        }

        /// <summary>
        /// Retourne le nom de l'application
        /// </summary>
        public override string Name
        {
            get { return "BlueCurve CrawlingApplication"; }
        }
    }
}